using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Blople.GameScenes;
using System.Xml;
using System.IO;

namespace Blople
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D backgroundTexture;
        Texture2D actionBackgroundTexture;
        Texture2D pauseScreenTexture;
        Texture2D menuTexture;
        Texture2D logoTexture;
        Texture2D blopTexture;
        Texture2D pointerTexture;
        Texture2D lineTexture;
        Texture2D inputTextTexture;
        Texture2D cursorTexture;
        Texture2D blockTexture;
        Texture2D arrowTexture;
        Texture2D spaceTexture;
        Texture2D pTexture;
        Texture2D escapeTexture;

        Song ingameSong;
        Song outgameSong;

        SpriteFont largeFont;
        SpriteFont mediumFont;
        SpriteFont smallFont;
        
        GameScene activeScene;
        StartScene startScene;
        MenuScene menuScene;
        LevelScene levelScene;
        ActionScene actionScene;
        EndScene endScene;
        HelpScene helpScene;
        HighScoreScene highscoreScene;
        CreditScene creditScene;

        KeyboardState oldKeyboardState;
        GamePadState oldGamepadState;


        HighScoreData data;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.IsFullScreen = false;
            graphics.PreferredBackBufferHeight = 800;
            graphics.PreferredBackBufferWidth = 500;
        }

        protected override void Initialize()
        {
            string fullpath = "highscores.xml";
            if (!File.Exists(fullpath))
            {
                data = new HighScoreData(9);

                data.Name[0] = "-";
                data.Score[0] = 0;
                data.Level[0] = 1;

                data.Name[1] = "-";
                data.Score[1] = 0;
                data.Level[1] = 1;

                data.Name[2] = "-";
                data.Score[2] = 0;
                data.Level[2] = 1;

                data.Name[3] = "-";
                data.Score[3] = 0;
                data.Level[3] = 2;

                data.Name[4] = "-";
                data.Score[4] = 0;
                data.Level[4] = 2;

                data.Name[5] = "-";
                data.Score[5] = 0;
                data.Level[5] = 2;

                data.Name[6] = "-";
                data.Score[6] = 0;
                data.Level[6] = 3;

                data.Name[7] = "-";
                data.Score[7] = 0;
                data.Level[7] = 3;

                data.Name[8] = "-";
                data.Score[8] = 0;
                data.Level[8] = 3;

                HighScoreData.SaveHighScores(data);
                
            }
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);

            largeFont = Content.Load<SpriteFont>("Arial");
            mediumFont = Content.Load<SpriteFont>("MediumArial");
            smallFont = Content.Load<SpriteFont>("SmallArial");

            backgroundTexture = Content.Load<Texture2D>("Background");
            actionBackgroundTexture = Content.Load<Texture2D>("ActionBackground");
            pauseScreenTexture = Content.Load<Texture2D>("PauseScreen");
            menuTexture = Content.Load<Texture2D>("Menu");
            logoTexture = Content.Load<Texture2D>("Logo");
            blopTexture = Content.Load<Texture2D>("Blops");
            pointerTexture = Content.Load<Texture2D>("Pointer");
            lineTexture = Content.Load<Texture2D>("Line");
            inputTextTexture = Content.Load<Texture2D>("InputText");
            cursorTexture = Content.Load<Texture2D>("Cursor");
            blockTexture = Content.Load<Texture2D>("Block");
            arrowTexture = Content.Load<Texture2D>("Arrow");
            spaceTexture = Content.Load<Texture2D>("Space");
            pTexture = Content.Load<Texture2D>("P");
            escapeTexture = Content.Load<Texture2D>("Escape");

            ingameSong = Content.Load<Song>("Ingame");
            outgameSong = Content.Load<Song>("Outgame");

            startScene = new StartScene(this, backgroundTexture, logoTexture, mediumFont);
            Components.Add(startScene);

            menuScene = new MenuScene(this, backgroundTexture, menuTexture, logoTexture, outgameSong, largeFont);
            Components.Add(menuScene);

            levelScene = new LevelScene(this, backgroundTexture, menuTexture, logoTexture, largeFont);
            Components.Add(levelScene);

            actionScene = new ActionScene(this, actionBackgroundTexture, pauseScreenTexture, lineTexture, blopTexture, pointerTexture, ingameSong, mediumFont);
            Components.Add(actionScene);

            endScene = new EndScene(this, backgroundTexture, inputTextTexture, cursorTexture, mediumFont);
            Components.Add(endScene);

            helpScene = new HelpScene(this, backgroundTexture, blockTexture, arrowTexture, spaceTexture, pTexture, escapeTexture, largeFont, smallFont);
            Components.Add(helpScene);

            highscoreScene = new HighScoreScene(this, backgroundTexture, blockTexture, largeFont, mediumFont, smallFont);
            Components.Add(highscoreScene);

            creditScene = new CreditScene(this, backgroundTexture, blockTexture, largeFont, mediumFont, smallFont);
            Components.Add(creditScene);

            startScene.Show();
            activeScene = startScene;
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            HandleScenesInputOnComputer();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin();
            base.Draw(gameTime);
            spriteBatch.End();
        }

        public void RecreateActionScene()
        {
            Components.Remove(actionScene);
            actionScene = new ActionScene(this, actionBackgroundTexture, pauseScreenTexture, lineTexture, blopTexture, pointerTexture, ingameSong, mediumFont);
            Components.Add(actionScene);
        }

        public void HandleScenesInputOnComputer()
        {
            if (activeScene == startScene) 
            {
                HandleStartSceneInputOnComputer();
            }
            else if (activeScene == menuScene) 
            {
                HandleMenuSceneInputOnComputer();
            }
            else if (activeScene == levelScene)
            {
                HandleLevelSceneInputOnComputer();
            }
            else if (activeScene == actionScene) 
            {
                HandleActionSceneInputOnComputer();
            }
            else if (activeScene == endScene)
            {
                HandleEndSceneInputOnComputer();
            }
            else if (activeScene == helpScene) 
            {
                HandleHelpSceneInputOnComputer();
            }
            else if (activeScene == highscoreScene) 
            {
                HandleHighScoreSceneInputOnComputer();      
            }
            else if (activeScene == creditScene) 
            {
                HandleCreditSceneInputOnComputer();
            }
        }

        public void HandleStartSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool entered = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter)));
            oldKeyboardState = keyboardState;

            if (entered)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleMenuSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool entered = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter)));
            oldKeyboardState = keyboardState;

            if (entered)
            {
                switch (menuScene.SelectedMenuIndex)
                {
                    case 0:
                        ShowScene(levelScene);
                        break;
                    case 1:
                        ShowScene(helpScene);
                        break;
                    case 2:
                        ShowScene(highscoreScene);
                        break;
                    case 3:
                        ShowScene(creditScene);
                        break;
                    case 4:
                        Exit();
                        break;
                }
            }
        }

        public void HandleLevelSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool entered = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter)));
            oldKeyboardState = keyboardState;

                if (entered)
                {
                    switch (levelScene.SelectedMenuIndex)
                    {
                        case 0:
                            actionScene.Level = 1;
                            ShowScene(actionScene);
                            break;
                        case 1:
                            actionScene.Level = 2;
                            ShowScene(actionScene);
                            break;
                        case 2:
                            actionScene.Level = 3;
                            ShowScene(actionScene);
                            break;
                        case 3:
                            ShowScene(menuScene);
                            break;
                    }
                }
        }

        public void HandleActionSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool left = keyboardState.IsKeyDown(Keys.Left);
            bool right = keyboardState.IsKeyDown(Keys.Right);
            bool space = (oldKeyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyUp(Keys.Left));
            bool escaped = (oldKeyboardState.IsKeyDown(Keys.Escape) && (keyboardState.IsKeyUp(Keys.Escape)));
            oldKeyboardState = keyboardState;

            if (left) 
            {
                actionScene.AimLeft(1.0f);
            }
            if (right) 
            {
                actionScene.AimRight(1.0f);
            }
            if (space) 
            {
                actionScene.Shoot();
            }
            if (escaped)
            {
                RecreateActionScene();
                ShowScene(menuScene);
            }
            if (actionScene.GameOver) {
                endScene.Level = actionScene.Level;
                endScene.Score = actionScene.Score;
                RecreateActionScene();
                ShowScene(endScene);
            }
        }

        public void HandleEndSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool entered = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter)));
            oldKeyboardState = keyboardState;

            if (entered)
            {
                if (endScene.SaveScoreAndUser()) {
                    ShowScene(highscoreScene);
                }
            }

        }

        public void HandleHelpSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool escaped = (oldKeyboardState.IsKeyDown(Keys.Escape) && (keyboardState.IsKeyUp(Keys.Escape)));
            oldKeyboardState = keyboardState;

            if (escaped)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleHighScoreSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool escaped = (oldKeyboardState.IsKeyDown(Keys.Escape) && (keyboardState.IsKeyUp(Keys.Escape)));
            oldKeyboardState = keyboardState;

            if (escaped)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleCreditSceneInputOnComputer()
        {
            KeyboardState keyboardState = Keyboard.GetState();
            bool escaped = (oldKeyboardState.IsKeyDown(Keys.Escape) && (keyboardState.IsKeyUp(Keys.Escape)));
            oldKeyboardState = keyboardState;

            if (escaped)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleSceneInputOnGamePad()
        {
            if (activeScene == startScene)
            {
                HandleStartSceneInputOnGamePad();
            }
            else if (activeScene == menuScene)
            {
                HandleMenuSceneInputOnGamePad();
            }
            else if (activeScene == levelScene)
            {
                HandleLevelSceneInputOnGamePad();
            }
            else if (activeScene == actionScene)
            {
                HandleActionSceneInputOnGamePad();
            }
            else if (activeScene == endScene)
            {
                HandleEndSceneInputOnGamePad();
            }
            else if (activeScene == helpScene)
            {
                HandleHelpSceneInputOnGamePad();
            }
            else if (activeScene == highscoreScene)
            {
                HandleHighScoreSceneInputOnGamePad();
            }
            else if (activeScene == creditScene)
            {
                HandleCreditSceneInputOnGamePad();
            }
        }

        public void HandleStartSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonA = (oldGamepadState.IsButtonDown(Buttons.A) && gamepadState.IsButtonUp(Buttons.A));
            oldGamepadState = gamepadState;

            if (buttonA) 
            {
                ShowScene(menuScene);
            }
        }

        public void HandleMenuSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonA = (oldGamepadState.IsButtonDown(Buttons.A) && gamepadState.IsButtonUp(Buttons.A));
            oldGamepadState = gamepadState;

            if (buttonA)
            {
                    switch (menuScene.SelectedMenuIndex)
                    {
                        case 0:
                            ShowScene(levelScene);
                            break;
                        case 1:
                            ShowScene(helpScene);
                            break;
                        case 2:
                            ShowScene(highscoreScene);
                            break;
                        case 3:
                            ShowScene(creditScene);
                            break;
                        case 4:
                            Exit();
                            break;
                    }
            }
        }

        public void HandleLevelSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonA = (oldGamepadState.IsButtonDown(Buttons.A) && gamepadState.IsButtonUp(Buttons.A));
            oldGamepadState = gamepadState;

            if (buttonA)
            {
                switch (menuScene.SelectedMenuIndex)
                {
                    case 0:
                        actionScene.Level = 1;
                        ShowScene(actionScene);
                        break;
                    case 1:
                        actionScene.Level = 2;
                        ShowScene(actionScene);
                        break;
                    case 2:
                        actionScene.Level = 3;
                        ShowScene(actionScene);
                        break;
                    case 3:
                        ShowScene(menuScene);
                        break;
                }
            }
        }

        public void HandleActionSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonA = (oldGamepadState.IsButtonDown(Buttons.A) && gamepadState.IsButtonUp(Buttons.A));
            bool buttonB = (oldGamepadState.IsButtonDown(Buttons.B) && gamepadState.IsButtonUp(Buttons.B));
            oldGamepadState = gamepadState;
            if (gamepadState.ThumbSticks.Left.X <= 0.0f) {
                actionScene.AimLeft(gamepadState.ThumbSticks.Left.X);
            }
            if (gamepadState.ThumbSticks.Left.X > 0.0f) {
                actionScene.AimLeft(gamepadState.ThumbSticks.Left.X);
            }

            if (buttonA)
            {
                actionScene.Shoot();
            }
            if (buttonB)
            {
                RecreateActionScene();
                ShowScene(menuScene);
            }
            if (actionScene.GameOver)
            {
                endScene.Level = actionScene.Level;
                endScene.Score = actionScene.Score;
                RecreateActionScene();
                ShowScene(endScene);
            }

        }

        public void HandleEndSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonA = (oldGamepadState.IsButtonDown(Buttons.A) && gamepadState.IsButtonUp(Buttons.A));
            oldGamepadState = gamepadState;

            if (buttonA)
            {
                if (endScene.SaveScoreAndUser())
                {
                    ShowScene(highscoreScene);
                }
            }
            
        }

        public void HandleHelpSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonB = (oldGamepadState.IsButtonDown(Buttons.B) && gamepadState.IsButtonUp(Buttons.B));
            oldGamepadState = gamepadState;

            if (buttonB)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleHighScoreSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonB = (oldGamepadState.IsButtonDown(Buttons.B) && gamepadState.IsButtonUp(Buttons.B));
            oldGamepadState = gamepadState;

            if (buttonB)
            {
                ShowScene(menuScene);
            }
        }

        public void HandleCreditSceneInputOnGamePad()
        {
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            bool buttonB = (oldGamepadState.IsButtonDown(Buttons.B) && gamepadState.IsButtonUp(Buttons.B));
            oldGamepadState = gamepadState;

            if (buttonB)
            {
                ShowScene(menuScene);
            }
        }

        protected void ShowScene(GameScene scene)
        {
            activeScene.Hide();
            activeScene = scene;
            scene.Show();
        }
    }
}
